package org.sws.domain.strategy.service.rule.chain.factory;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.sws.domain.strategy.enums.LogicModel;
import org.sws.domain.strategy.model.entity.StrategyEntity;
import org.sws.domain.strategy.repository.IStrategyRepository;
import org.sws.domain.strategy.service.rule.chain.ILogicChain;
import org.sws.types.enums.ResponseCode;
import org.sws.types.exception.AppException;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author sws
 * @Date 2025/2/24 16:13
 * @description: 策略抽奖规则链工厂
 */
@Slf4j
@Component
public class LogicChainFactory {

    private final Map<String, ILogicChain> logicChainMap;

    private final IStrategyRepository repository;

    LogicChainFactory(Map<String, ILogicChain> logicChainMap, IStrategyRepository repository){
        this.logicChainMap = logicChainMap;
        this.repository = repository;
    }

    // 构造某策略的规则过滤责任链
    public ILogicChain createLogicChain(Long strategyId){
        StrategyEntity strategy = repository.queryStrategyEntityByStrategyId(strategyId);
        if(Objects.isNull(strategy)){
            log.warn("抽奖策略查询不存在，ID：{}", strategyId);
            throw new AppException(ResponseCode.STRATEGY_IS_NULL.getCode(), ResponseCode.STRATEGY_IS_NULL.getInfo());
        }
        String[] ruledModels = strategy.ruleModels();
        if(null == ruledModels || 0 == ruledModels.length){
            return logicChainMap.get(LogicModel.RULE_DEFAULT.getCode());
        }
        List<String> beforeLogicList = LogicModel.getBeforeLogic();
        List<String> filterLogic = beforeLogicList.stream().filter(ruleModel -> Arrays.asList(ruledModels).contains(ruleModel)).collect(Collectors.toList());

        ILogicChain logicChain = logicChainMap.get(filterLogic.get(0));
        ILogicChain current = logicChain;
        for (int i = 1; i < filterLogic.size(); i++) {
            ILogicChain nextChain = logicChainMap.get(filterLogic.get(i));
            current = current.appendNext(nextChain);
        }
        current.appendNext(logicChainMap.get(LogicModel.RULE_DEFAULT.getCode()));
        return logicChain;
    }
}
